package com.hzy.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.hzy.constant.ConfigConstants;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 环信工具类
 */
public class IMUtil {
    private static final Logger logger = LoggerFactory.getLogger(IMUtil.class);
    private static RedisUtils redisUtils = null;

    public IMUtil() {
    }

    public IMUtil(RedisUtils redisUtils) {
        redisUtils = redisUtils;
    }

    private static OkHttpClient client = new OkHttpClient();
    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");

    /**
     * 获取统一的请求头，不携带token
     *
     * @return 请求头
     */
    private static Request.Builder getRequestBuilderHead() {
        return new Request.Builder().addHeader("Content-Type", "application/json");
    }

    /**
     * 获取统一的请求头，携带token
     *
     * @return 请求头
     */
    private static Request.Builder getRequestBuilderHeadWithToken() {
        return new Request.Builder()
                .addHeader("Content-Type", "application/json")
                .addHeader("Authorization", "Bearer " + getToken());
    }

    /**
     * 获取统一的请求头，携带token，没有content-type
     *
     * @return 请求头
     */
    private static Request.Builder getRequestBuilderHeadWithoutCT() {
        return new Request.Builder()
                .addHeader("Authorization", "Bearer " + getToken());
    }

    /**
     * 获取统一的请求头，携带token，没有content-type
     *
     * @return 请求头
     */
    private static Request.Builder getRequestBuilderHeadUpload() {
        return new Request.Builder()
                .addHeader("Authorization", "Bearer " + getToken())
                .addHeader("restrict-access", "true");
    }

    /**
     * 初始化获得token
     */
    private static String initToken() {
        String body = "{\"grant_type\":\"client_credentials\",\"client_id\":\"" + ConfigConstants.HX_CLIENT_ID
                + "\",\"client_secret\":\"" + ConfigConstants.HX_CLIENT_SECRET + "\" }";
        Request request = getRequestBuilderHead().url(ConfigConstants.HX_URL + "token")
                                                 .post(RequestBody.create(JSON, body))
                                                 .build();
        Response response;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
            logger.info("无法获取环信token", ConfigConstants.LOG_WARN);
            return ConfigConstants.ERROR_LOW;
        }
        //请求是否成功
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            //响应体是否为空
            if (responseBody == null) {
                logger.info("响应体为空", ConfigConstants.LOG_WARN);
                return ConfigConstants.ERROR_LOW;
            }
            try {
                JSONObject jsonObject = JSONObject.parseObject(responseBody.string());
                // 插入时间
                redisUtils.set(ConfigConstants.HX_TOKEN, jsonObject.get("access_token").toString());
                // 设置过期时间
                redisUtils.expire(ConfigConstants.HX_TOKEN, Integer.valueOf(String.valueOf(jsonObject.get("expires_in"))));
                return String.valueOf(jsonObject.get("access_token"));
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            logger.info("环信token请求失败", ConfigConstants.LOG_WARN);
        }
        logger.info("环信token未知错误", ConfigConstants.LOG_ERROR);
        return ConfigConstants.ERROR_LOW;
    }

    /**
     * 获取缓存中的环信token，若是没有，通过请求获取
     *
     * @return token
     */
    private static String getToken() {
        if (!redisUtils.hasKey(ConfigConstants.HX_TOKEN)) {
            String token = initToken();
            if (token.equals(ConfigConstants.ERROR_LOW)) {
                token = initToken();
                return token;
            } else {
                return token;
            }
        }
        return (String) redisUtils.get(ConfigConstants.HX_TOKEN);
    }

    /**
     * 注册用户
     *
     * @param userId   用户id
     * @param password 用户密码，一般来说用一个固定值，方便用户登录
     *
     * @return 成功/失败
     */
    public boolean registerUser(String userId, String password, String nickname) throws Exception {
        String body = "{\"username\":\"" + userId + "\",\"password\":\"" + password + "\", \"nickname\":\""
                + nickname + "\"}";
        Request request = getRequestBuilderHeadWithToken().url(ConfigConstants.HX_URL + "users")
                                                          .post(RequestBody.create(JSON, body))
                                                          .build();
        Response response;
        response = client.newCall(request).execute();
        //请求是否成功
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            //响应体是否为空
            if (responseBody == null) {
                logger.info("注册用户时，响应体为空", ConfigConstants.LOG_WARN);
                return false;
            }
            JSONObject jsonObject = JSONObject.parseObject(responseBody.string());
            System.out.println(jsonObject.get("entities"));
            return true;
        } else {
            logger.info("注册用户，请求失败", ConfigConstants.LOG_WARN);
            return false;
        }
    }

    /**
     * 修改昵称
     *
     * @param userId   就是环信的username
     * @param nickname 要修改的昵称
     *
     * @return 成功/失败
     *
     * @throws Exception 用来回滚事务
     */
    public static boolean updateNickname(int userId, String nickname) throws Exception {
        String body = "{ \"nickname\":\"" + nickname + "\"}";
        Request request = getRequestBuilderHeadWithToken().url(ConfigConstants.HX_URL + "users/" + userId)
                                                          .put(RequestBody.create(JSON, body))
                                                          .build();
        Response response = client.newCall(request).execute();
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            if (responseBody == null) {
                logger.info("修改昵称时，响应体为空", ConfigConstants.LOG_WARN);
                return false;
            }
            //JSONObject jsonObject = JSONObject.parseObject(responseBody.string());
            //JSONArray entities = jsonObject.getJSONArray("entities");
            //System.out.println(JSONObject.parseObject(String.valueOf(entities.get(0))).get("nickname"));
            return true;
        } else {
            logger.info("修改昵称，请求失败", ConfigConstants.LOG_WARN);
            return false;
        }

    }

    /**
     * 获取该用户的好友列表
     *
     * @param userId 用户id
     *
     * @return username
     */
    public static List<String> listFriends(int userId) {
        Request request = getRequestBuilderHeadWithToken().url(ConfigConstants.HX_URL + "users/" + userId + "/contacts/users")
                                                          .get()
                                                          .build();
        Response response = null;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
            logger.info("好友列表， 执行失败", ConfigConstants.LOG_WARN);
            return null;
        }
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            if (responseBody == null) {
                logger.info("好友列表， 响应体为空", ConfigConstants.LOG_WARN);
                return null;
            }
            JSONArray data;
            try {
                data = JSONObject.parseObject(responseBody.string()).getJSONArray("data");
            } catch (IOException e) {
                logger.info("好友列表，没有响应体", ConfigConstants.LOG_WARN);
                e.printStackTrace();
                return null;
            }
            if (data == null) {
                return null;
            }
            return JSONArray.parseArray(data.toJSONString(), String.class);
        } else {
            logger.info("好友列表，请求失败", ConfigConstants.LOG_WARN);
            return null;
        }
    }

    /**
     * 获取该用户的好友数量
     *
     * @param userId 用户id
     *
     * @return 好友数量
     */
    public static int friendsNum(int userId) {
        Request request = getRequestBuilderHeadWithToken().url(ConfigConstants.HX_URL + "users/" + userId + "/contacts/users")
                                                          .get()
                                                          .build();
        Response response;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            logger.info("响应失败", ConfigConstants.LOG_WARN);
            e.printStackTrace();
            return 0;
        }
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            if (responseBody == null) {
                logger.info("好友数量， 响应体为空", ConfigConstants.LOG_WARN);
                return 0;
            }
            try {
                return (int) JSONObject.parseObject(responseBody.string()).get("count");
            } catch (IOException e) {
                e.printStackTrace();
                logger.info("好友数量，解析responseBody失败", ConfigConstants.LOG_WARN);
                return 0;
            }
        } else {
            logger.info("好友数量，请求失败", ConfigConstants.LOG_WARN);
            return 0;
        }
    }


    /**
     * 根据type得到给谁发消息
     *
     * @param type 0:users 给用户发消息。 1:chatgroups: 给群发消息，2:chatrooms: 给聊天室发消息
     *
     * @return 对应类型
     */
    private static String getTargetType(int type) {
        switch (type) {
            case 0:
                return "users";
            case 1:
                return "chatgroups";
            case 2:
                return "chatrooms";
            default:
                return null;
        }
    }

    /**
     * 发送文字消息
     *
     * @param fromId   发消息的用户
     * @param targetId 收消息的用户
     * @param type     0给用户发消息 1给群发消息 2给聊天室发消息
     *
     * @return 成功/失败
     */
    @Deprecated
    public static boolean sendTextMsg(int fromId, int targetId, String msg, int type) {
        String targetType = getTargetType(type);
        if (targetType == null) {
            return false;
        }
        String body = "{ \"target_type\" : \"" + targetType + "\"," +
                " \"target\" : [\"" + targetId + "\"], " +
                "\"msg\" : {\"type\" : \"txt\"," + " \"msg\" : \"" + msg + "\" }, " +
                "\"from\" : \"" + fromId + "\" }";
        Request request = getRequestBuilderHeadWithToken().url(ConfigConstants.HX_URL + "messages")
                                                          .post(RequestBody.create(JSON, body))
                                                          .build();
        Response response;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
            logger.info("发送文字消息，响应异常", ConfigConstants.LOG_WARN);
            return false;
        }
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            if (responseBody == null) {
                logger.info("发送文字消息，响应为null", ConfigConstants.LOG_WARN);
                return false;
            }
            try {
                JSONObject jsonObject = JSONObject.parseObject(responseBody.string());
                System.out.println(jsonObject);
                //查看消息是否发送成功
                return JSONObject.parseObject(jsonObject.get("data").toString()).get(String.valueOf(targetId))
                                 .equals(ConfigConstants.SUCCESS_LOW);
            } catch (IOException e) {
                e.printStackTrace();
                logger.info("发送文字消息，抛出异常", ConfigConstants.LOG_WARN);
                return false;
            }
        } else {
            logger.info("发送文字消息失败", ConfigConstants.LOG_WARN);
            return false;
        }
    }

    /**
     * 发送文本消息
     *
     * @param fromId   发消息的用户
     * @param targetId 收消息的用户
     * @param type     0给用户发消息 1给群发消息 2给聊天室发消息
     *
     * @return 成功/失败
     */
    @Deprecated
    public static boolean sendPicMsg(int fromId, int targetId, int type) {
        String targetType = getTargetType(type);
        if (targetType == null) {
            return false;
        }
        String body = "{  \"target_type\" : \"users\",   " +
                "    \"target\" : [\"" + targetId + "\"]," +
                "    \"msg\" : {  " +
                "        \"type\" : \"img\",  " +
                "        \"url\":" +
                " \"https://a1.easemob.com/1104190225107627/happycrowd/chatfiles/23e205a0-3a84-11e9-bd00-150f049443ac\", "
                +
                "        \"filename\": \"24849.jpg\", " +
                "        \"secret\": \"I-IFqjqEEemK-iFZVwesGBrwnF70uuwy-fwpA7e-wSVO6p9L\", " +
                "        \"size\" : {" +
                "          \"width\" : 480," +
                "          \"height\" : 720" +
                "      }" +
                "     }," +
                "    \"from\" : \"" + fromId + "\" }";
        Request request = getRequestBuilderHeadWithToken().url(ConfigConstants.HX_URL + "messages")
                                                          .post(RequestBody.create(JSON, body))
                                                          .build();
        Response response;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
            logger.info("发送图片消息，响应异常", ConfigConstants.LOG_WARN);
            return false;
        }
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            if (responseBody == null) {
                logger.info("发送图片消息，响应为null", ConfigConstants.LOG_WARN);
                return false;
            }
            try {
                JSONObject jsonObject = JSONObject.parseObject(responseBody.string());
                //查看消息是否发送成功
                return JSONObject.parseObject(jsonObject.get("data").toString()).get(String.valueOf(targetId))
                                 .equals(ConfigConstants.SUCCESS_LOW);
            } catch (IOException e) {
                e.printStackTrace();
                logger.info("发送图片消息，抛出异常", ConfigConstants.LOG_WARN);
                return false;
            }
        } else {
            logger.info("发送图片消息失败", ConfigConstants.LOG_WARN);
            return false;
        }
    }

    /**
     * 上传文件
     *
     * @param url      文件路径
     * @param fileName 上传的文件名称
     *
     * @return 成功/失败
     */
    @Deprecated
    public static boolean upload(String url, String fileName) {
        Request request = getRequestBuilderHeadUpload().url(ConfigConstants.HX_URL + "chatfiles")
                                                       .post(new MultipartBody.Builder()
                                                               .setType(MultipartBody.FORM)
                                                               .addFormDataPart("file", fileName,
                                                                       RequestBody.create(MediaType.parse("image/png")
                                                                               , new File(url)))
                                                               .build())
                                                       .build();
        Response response;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
            logger.info("上传文件，响应异常", ConfigConstants.LOG_WARN);
            return false;
        }
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            if (responseBody == null) {
                logger.info("上传文件，响应为null", ConfigConstants.LOG_WARN);
                return false;
            }
            try {
                JSONObject jsonObject = JSONObject.parseObject(responseBody.string());
                if (jsonObject.isEmpty()) {
                    return false;
                }
                if (jsonObject.get("entities") == null) {
                    return false;
                }
                JSONArray jsonArray = JSONArray.parseArray(String.valueOf(jsonObject.get("entities")));
                MessageFile file = new MessageFile();
                file.setUuid(JSONObject.parseObject(String.valueOf(jsonArray.get(0))).getString("uuid"));
                file.setSecret(JSONObject.parseObject(String.valueOf(jsonArray.get(0))).getString("share-secret"));
                System.out.println(file.getSecret());
                System.out.println(file.getUuid());
                return false;
            } catch (IOException e) {
                e.printStackTrace();
                logger.info("上传文件，抛出异常", ConfigConstants.LOG_WARN);
                return false;
            }
        } else {
            logger.info("上传文件", ConfigConstants.LOG_WARN);
            return false;
        }
    }

    /**
     * 消息里的文件实体类
     */
    static class MessageFile {
        private String uuid;
        private String secret;

        String getUuid() {
            return uuid;
        }

        void setUuid(String uuid) {
            this.uuid = uuid;
        }

        String getSecret() {
            return secret;
        }

        void setSecret(String secret) {
            this.secret = secret;
        }
    }

    public static boolean addFriends(int ownerUserId, int friendUserId) {
        Request request = getRequestBuilderHeadWithToken()
                .url(ConfigConstants.HX_URL + "users/" + ownerUserId + "/contacts/users/" + friendUserId)
                .post(RequestBody.create(null, ""))
                .build();
        OkHttpClient client = new OkHttpClient();
        Response response = null;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (response == null) {
            return false;
        }
        //请求是否成功
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            //响应体是否为空
            if (responseBody == null) {
                logger.info("响应体为空", ConfigConstants.LOG_WARN);
                return false;
            }
            try {
                JSONObject jsonObject = JSONObject.parseObject(responseBody.string());
                System.out.println(jsonObject);
                return true;
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            logger.info("添加好友，环信token请求失败", ConfigConstants.LOG_WARN);
            return false;
        }
        logger.info("添加好友,环信token未知错误", ConfigConstants.LOG_ERROR);
        return false;
    }


    public static boolean delFriends(int ownerUserId, int friendUserId) {
        Request request = getRequestBuilderHeadWithToken()
                .url(ConfigConstants.HX_URL + "users/" + ownerUserId + "/contacts/users/" + friendUserId)
                .delete()
                .build();
        OkHttpClient client = new OkHttpClient();
        Response response = null;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (response == null) {
            return false;
        }
        //请求是否成功
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            //响应体是否为空
            if (responseBody == null) {
                logger.info("响应体为空", ConfigConstants.LOG_WARN);
                return false;
            }
            try {
                JSONObject jsonObject = JSONObject.parseObject(responseBody.string());
                System.out.println(jsonObject);
                return true;
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            logger.info("删除好友，环信token请求失败", ConfigConstants.LOG_WARN);
            return false;
        }
        logger.info("删除好友,环信token未知错误", ConfigConstants.LOG_ERROR);
        return false;
    }

    /**
     * groupname	群组名称，此属性为必须的
     * desc	群组描述，此属性为必须的
     * public	是否是公开群，此属性为必须的
     * maxusers	群组成员最大数（包括群主），值为数值类型，默认值200，最大值2000，此属性为可选的
     * members_only	加入群是否需要群主或者群管理员审批，默认是false
     * allowinvites	是否允许群成员邀请别人加入此群。 true：允许群成员邀请人加入此群，false：只有群主或者管理员才可以往群里加人。
     * owner	群组的管理员，此属性为必须的  注意！这个字段为string类型
     * members	群组成员，此属性为可选的，但是如果加了此项，数组元素至少一个（注：群主user1不需要写入到members里面）
     *
     * @return 群组id
     */
    public static String createGroup(Map<String, Object> map) {
        Request request = getRequestBuilderHeadWithToken().url(ConfigConstants.HX_URL + "chatgroups")
                                                          .post(RequestBody.create(JSON, JSONObject.toJSONString(map)))
                                                          .build();
        OkHttpClient client = new OkHttpClient();
        Response response;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            logger.info("创建群组，响应体解析异常", ConfigConstants.LOG_WARN);
            e.printStackTrace();
            return "";
        }
        if (response == null) {
            return "";
        }
        //请求是否成功
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            //响应体是否为空
            if (responseBody == null) {
                logger.info("创建群组，响应体为空", ConfigConstants.LOG_WARN);
                return "";
            }
            try {
                JSONObject jsonObject = JSONObject.parseObject(responseBody.string());
                System.out.println(jsonObject);
                return JSONObject.parseObject(jsonObject.get("data").toString()).get("groupid").toString();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            logger.info("创建群组，环信token请求失败", ConfigConstants.LOG_WARN);
            return "";
        }
        logger.info("创建群组，环信token未知错误", ConfigConstants.LOG_ERROR);
        return "";
    }
    /**
     * 修改群组
     * groupname	群组名称，修改时值不能包含斜杠（“/“）
     * description	群组描述，修改时值不能包含斜杠（”/“）
     * maxusers	群组成员最大数（包括群主），值为数值类型
     *
     * @return 群组id
     */
    public static String updateGroup(Map<String, Object> map, String groupId) {
        Request request = getRequestBuilderHeadWithToken().url(ConfigConstants.HX_URL + "chatgroups" + "/" + groupId)
                .put(RequestBody.create(JSON, JSONObject.toJSONString(map)))
                .build();
        OkHttpClient client = new OkHttpClient();
        Response response;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            logger.info("修改群组，响应体解析异常", ConfigConstants.LOG_WARN);
            e.printStackTrace();
            return "";
        }
        if (response == null) {
            return "";
        }
        //请求是否成功
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            //响应体是否为空
            if (responseBody == null) {
                logger.info("修改群组，响应体为空", ConfigConstants.LOG_WARN);
                return "";
            }
            try {
                JSONObject jsonObject = JSONObject.parseObject(responseBody.string());
                System.out.println(jsonObject);
                return JSONObject.parseObject(jsonObject.get("data").toString()).toString();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            logger.info("修改群组，环信token请求失败", ConfigConstants.LOG_WARN);
            return "";
        }
        logger.info("修改群组，环信token未知错误", ConfigConstants.LOG_ERROR);
        return "";
    }

    /**
     * 删除群组
     * groupId	群组成员最大数（包括群主），值为数值类型
     *
     * @return 群组id
     */
    public static String deleteGroup(String groupId) {
        Request request = getRequestBuilderHeadWithToken().url(ConfigConstants.HX_URL + "chatgroups" + "/" + groupId)
                .delete()
                .build();
        OkHttpClient client = new OkHttpClient();
        Response response;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            logger.info("删除群组，响应体解析异常", ConfigConstants.LOG_WARN);
            e.printStackTrace();
            return "";
        }
        if (response == null) {
            return "";
        }
        //请求是否成功
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            //响应体是否为空
            if (responseBody == null) {
                logger.info("删除群组，响应体为空", ConfigConstants.LOG_WARN);
                return "";
            }
            try {
                JSONObject jsonObject = JSONObject.parseObject(responseBody.string());
                System.out.println(jsonObject);
                return JSONObject.parseObject(jsonObject.get("data").toString()).get("success").toString();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            logger.info("删除群组，环信token请求失败", ConfigConstants.LOG_WARN);
            return "";
        }
        logger.info("修改群组，环信token未知错误", ConfigConstants.LOG_ERROR);
        return "";
    }

    /**
     * 获取该用户加入的所有群组
     *
     * @param userId 用户id
     *
     * @return 群组列表，包含群组id与名称
     */
    public static List<Map> listGroup(int userId) {
        Request request = getRequestBuilderHeadWithToken()
                .url(ConfigConstants.HX_URL + "users/" + userId + "/joined_chatgroups")
                .build();
        OkHttpClient client = new OkHttpClient();
        Response response;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            logger.info("查看该用户加入的所有群组，响应体解析异常", ConfigConstants.LOG_WARN);
            e.printStackTrace();
            return new ArrayList<>(0);
        }
        if (response == null) {
            return new ArrayList<>(0);
        }
        //请求是否成功
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            //响应体是否为空
            if (responseBody == null) {
                logger.info("查看该用户加入的所有群组，响应体为空", ConfigConstants.LOG_WARN);
                return new ArrayList<>(0);

            }
            try {
                JSONObject jsonObject = JSONObject.parseObject(responseBody.string());
                System.out.println(jsonObject);
                return JSONArray.parseArray(String.valueOf(jsonObject.get("data")), Map.class);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            logger.info("查看该用户加入的所有群组，环信token请求失败", ConfigConstants.LOG_WARN);
            return new ArrayList<>(0);
        }
        logger.info("查看该用户加入的所有群组，环信token未知错误", ConfigConstants.LOG_ERROR);
        return new ArrayList<>(0);
    }

    /**
     * 获取该用户加入的群组数量
     *
     * @param userId 用户id
     *
     * @return 群组数量
     */
    public static int groupNum(int userId) {
        Request request = getRequestBuilderHeadWithToken()
                .url(ConfigConstants.HX_URL + "users/" + userId + "/joined_chatgroups")
                .build();
        OkHttpClient client = new OkHttpClient();
        Response response;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            logger.info("查看该用户加入的群组数量，响应体解析异常", ConfigConstants.LOG_WARN);
            e.printStackTrace();
            return 0;
        }
        if (response == null) {
            return 0;
        }
        //请求是否成功
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            //响应体是否为空
            if (responseBody == null) {
                logger.info("查看该用户加入的群组数量，响应体为空", ConfigConstants.LOG_WARN);
                return 0;

            }
            try {
                JSONObject jsonObject = JSONObject.parseObject(responseBody.string());
                System.out.println(jsonObject);
                return (int) jsonObject.get("count");
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            logger.info("查看该用户加入的群组数量，环信token请求失败", ConfigConstants.LOG_WARN);
            return 0;
        }
        logger.info("查看该用户加入的群组数量，环信token未知错误", ConfigConstants.LOG_ERROR);
        return 0;
    }

    /**
     * 获取群信息，可以获取一个或多个
     *
     * @param groupIds 群id，多个群组用逗号隔开
     *
     * @return 群的具体信息
     */
    public static List<Map<String, Object>> getGroupInfo(String groupIds) {
        Request request = getRequestBuilderHeadWithToken()
                .url(ConfigConstants.HX_URL + "chatgroups/" + groupIds)
                .build();
        OkHttpClient client = new OkHttpClient();
        Response response;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            logger.info("查看群组详细信息，响应体解析异常", ConfigConstants.LOG_WARN);
            e.printStackTrace();
            return new ArrayList<>(0);
        }
        if (response == null) {
            return new ArrayList<>(0);
        }
        //请求是否成功
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            //响应体是否为空
            if (responseBody == null) {
                logger.info("查看群组详细信息，响应体为空", ConfigConstants.LOG_WARN);
                return new ArrayList<>(0);
            }
            try {
                JSONObject jsonObject = JSONObject.parseObject(responseBody.string());
                return com.alibaba.fastjson.JSON.parseObject(String.valueOf(jsonObject.get("data")),
                        new TypeReference<List<Map<String, Object>>>() {
                        });
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            logger.info("查看群组详细信息，环信token请求失败", ConfigConstants.LOG_WARN);
            return new ArrayList<>(0);
        }
        logger.info("查看群组详细信息，环信token未知错误", ConfigConstants.LOG_ERROR);
        return new ArrayList<>(0);
    }

    /**
     * 拉黑用户，目前只拉黑一个用户
     *
     * @param userId  拉黑者用户
     * @param blackId 被拉黑用户id
     *
     * @return 群的具体信息
     */
    public static boolean blackAdd(int userId, int blackId) {
        Request request = getRequestBuilderHeadWithToken()
                .url(ConfigConstants.HX_URL + "users/" + userId + "/blocks/users")
                .post(RequestBody.create(JSON, "{ \"usernames\": [ \"" + blackId + "\" ] }"))
                .build();
        OkHttpClient client = new OkHttpClient();
        Response response;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            logger.info("拉黑用户，响应体解析异常", ConfigConstants.LOG_WARN);
            e.printStackTrace();
            return false;
        }
        if (response == null) {
            return false;
        }
        //请求是否成功
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            //响应体是否为空
            if (responseBody == null) {
                logger.info("拉黑用户，响应体为空", ConfigConstants.LOG_WARN);
                return false;
            }
            try {
                System.out.println(JSONObject.parseObject(responseBody.string()));
                return true;
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            logger.info("拉黑用户，环信token请求失败", ConfigConstants.LOG_WARN);
            return false;
        }
        logger.info("拉黑用户，环信token未知错误", ConfigConstants.LOG_ERROR);
        return false;
    }

    /**
     * 移除黑名单
     *
     * @param userId  拉黑者用户
     * @param blackId 被拉黑用户id
     *
     * @return 群的具体信息
     */
    public static boolean blackRemove(int userId, int blackId) {
        Request request = getRequestBuilderHeadWithToken()
                .url(ConfigConstants.HX_URL + "users/" + userId + "/blocks/users/" + blackId)
                .delete()
                .build();
        OkHttpClient client = new OkHttpClient();
        Response response;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            logger.info("移除对应黑名单，响应体解析异常", ConfigConstants.LOG_WARN);
            e.printStackTrace();
            return false;
        }
        if (response == null) {
            return false;
        }
        //请求是否成功
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            //响应体是否为空
            if (responseBody == null) {
                logger.info("移除对应黑名单，响应体为空", ConfigConstants.LOG_WARN);
                return false;
            }
            try {
                System.out.println(JSONObject.parseObject(responseBody.string()));
                return true;
            } catch (IOException e) {
                e.printStackTrace();
            }

        } else {
            logger.info("移除对应黑名单，环信token请求失败", ConfigConstants.LOG_WARN);
            return false;
        }
        logger.info("移除对应黑名单，环信token未知错误", ConfigConstants.LOG_ERROR);
        return false;
    }

    /**
     * 创建多人聊天室
     *
     * @param userId 用户id，即是聊天室管理员
     * @param name   聊天室名称
     * @param des    聊天室属性
     *
     * @return 群的具体信息
     */
    public static String roomCreate(int userId, String name, String des) {
        Map<String, String> requestBody = new HashMap<>();
        requestBody.put("owner", String.valueOf(userId));
        requestBody.put("name", name);
        requestBody.put("description", des);
        Request request = getRequestBuilderHeadWithToken()
                .url(ConfigConstants.HX_URL + "chatrooms")
                .post(RequestBody.create(JSON, JSONObject.toJSONString(requestBody)))
                .build();
        OkHttpClient client = new OkHttpClient();
        Response response;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            logger.info("创建聊天室，响应体解析异常", ConfigConstants.LOG_WARN);
            e.printStackTrace();
            return "";
        }
        if (response == null) {
            return "";
        }
        //请求是否成功
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            //响应体是否为空
            if (responseBody == null) {
                logger.info("创建聊天室，响应体为空", ConfigConstants.LOG_WARN);
                return "";
            }
            try {
                JSONObject data = JSONObject.parseObject(responseBody.string()).getJSONObject("data");
                if (StringUtils.isEmpty(data.toString())) {
                    logger.info("创建聊天室失败", ConfigConstants.LOG_WARN);
                    return "";
                }
                return data.get("id").toString();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            logger.info("创建聊天室，环信token请求失败", ConfigConstants.LOG_WARN);
            return "";
        }
        logger.info("创建聊天室，环信token未知错误", ConfigConstants.LOG_ERROR);
        return "";
    }

    /**
     * 删除聊天室
     *
     * @param roomId 房间id
     *
     * @return 成功/失败
     */
    public static boolean roomDelete(String roomId) {
        Request request = getRequestBuilderHeadWithToken()
                .url(ConfigConstants.HX_URL + "chatrooms/" + roomId)
                .delete()
                .build();
        OkHttpClient client = new OkHttpClient();
        Response response;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            logger.info("删除聊天室，响应体解析异常", ConfigConstants.LOG_WARN);
            e.printStackTrace();
            return false;
        }
        if (response == null) {
            return false;
        }
        //请求是否成功
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            //响应体是否为空
            if (responseBody == null) {
                logger.info("删除聊天室，响应体为空", ConfigConstants.LOG_WARN);
                return false;
            }
            try {
                JSONObject data = JSONObject.parseObject(responseBody.string()).getJSONObject("data");
                if (StringUtils.isEmpty(data.toString())) {
                    logger.info("删除聊天室", ConfigConstants.LOG_WARN);
                    return false;
                }
                return (boolean) data.get("success");
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            logger.info("删除聊天室，环信token请求失败", ConfigConstants.LOG_WARN);
            return false;
        }
        logger.info("删除聊天室，环信token未知错误", ConfigConstants.LOG_ERROR);
        return false;
    }


    /**
     * 获取聊天室里的用户列表
     *
     * @param roomId 房间id
     *
     * @return 用户列表
     */
    public static List<Map> roomMemberList(Object roomId) {
        Request request = getRequestBuilderHeadWithToken()
                .url(ConfigConstants.HX_URL + "chatrooms/" + roomId)
                .get()
                .build();
        OkHttpClient client = new OkHttpClient();
        Response response;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            logger.info("获取聊天室用户列表，响应体解析异常", ConfigConstants.LOG_WARN);
            e.printStackTrace();
            return null;
        }
        if (response == null) {
            return null;
        }
        //请求是否成功
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            //响应体是否为空
            if (responseBody == null) {
                logger.info("获取聊天室用户列表，响应体为空", ConfigConstants.LOG_WARN);
                return null;
            }
            try {
                JSONArray data = JSONObject.parseObject(responseBody.string()).getJSONArray("data");
                if (StringUtils.isEmpty(data.toString())) {
                    logger.info("获取聊天室用户列表,data为空", ConfigConstants.LOG_WARN);
                    return null;
                }
                JSONArray affiliations = ((JSONObject) data.get(0)).getJSONArray("affiliations");
                if (affiliations.isEmpty()) {
                    return null;
                }
                List<Map> list = JSONObject.parseArray(affiliations.toJSONString(), Map.class);
                return list.stream().filter(p -> p.get("member") != null).collect(Collectors.toList());
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            logger.info("获取聊天室用户列表，环信token请求失败", ConfigConstants.LOG_WARN);
            return null;
        }
        logger.info("获取聊天室用户列表，环信token未知错误", ConfigConstants.LOG_ERROR);
        return null;
    }

    /**
     * 获取聊天室里的用户人数，包括观众与主播
     *
     * @param roomId 房间id
     *
     * @return 用户人数
     */
    public static int roomUserCount(Object roomId) {
        Request request = getRequestBuilderHeadWithToken()
                .url(ConfigConstants.HX_URL + "chatrooms/" + roomId)
                .get()
                .build();
        OkHttpClient client = new OkHttpClient();
        Response response;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            logger.info("获取聊天室用户人数，响应体解析异常", ConfigConstants.LOG_WARN);
            e.printStackTrace();
            return 0;
        }
        if (response == null) {
            return 0;
        }
        //请求是否成功
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            //响应体是否为空
            if (responseBody == null) {
                logger.info("获取聊天室用户人数，响应体为空", ConfigConstants.LOG_WARN);
                return 0;
            }
            try {
                JSONArray data = JSONObject.parseObject(responseBody.string()).getJSONArray("data");
                if (StringUtils.isEmpty(data.toString())) {
                    logger.info("获取聊天室用户人数,data为空", ConfigConstants.LOG_WARN);
                    return 0;
                }
                Integer affiliationsCount = (Integer) ((JSONObject) data.get(0)).get("affiliations_count");
                if (affiliationsCount == null) {
                    return 0;
                }
                return affiliationsCount;
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            logger.info("获取聊天室用户人数，环信token请求失败", ConfigConstants.LOG_WARN);
            return 0;
        }
        logger.info("获取聊天室用户人数，环信token未知错误", ConfigConstants.LOG_ERROR);
        return 0;
    }


    /**
     * 删除用户
     *
     * @param userId 拉黑者用户
     *
     * @return 群的具体信息
     */
    public static boolean userRemove(String userId) {
        Request request = getRequestBuilderHeadWithToken()
                .url(ConfigConstants.HX_URL + "users/" + userId)
                .delete()
                .build();
        OkHttpClient client = new OkHttpClient();
        Response response;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            logger.info("删除用户，响应体解析异常", ConfigConstants.LOG_WARN);
            e.printStackTrace();
            return false;
        }
        if (response == null) {
            return false;
        }
        //请求是否成功
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            //响应体是否为空
            if (responseBody == null) {
                logger.info("删除用户，响应体为空", ConfigConstants.LOG_WARN);
                return false;
            }
            try {
                System.out.println(JSONObject.parseObject(responseBody.string()));
                return true;
            } catch (IOException e) {
                e.printStackTrace();
            }

        } else {
            logger.info("删除用户，环信token请求失败", ConfigConstants.LOG_WARN);
            return false;
        }
        logger.info("删除用户，环信token未知错误", ConfigConstants.LOG_ERROR);
        return false;
    }


// --------------------------------------------- 群成员 ---------------------------------------------------
    /**
     * 批量添加群成员
     * 为群组添加多个成员，一次最多可以添加60位成员。如果所有用户均已是群成员，将添加失败，并返回错误。
     * groupId	群组id
     * username	环信用户id 数组
     *
     * @return 添加结果，true表示添加成功，false表示添加失败
     */
    public static boolean batchAddGroupMember(String groupId, Map map) {
        Request request = getRequestBuilderHeadWithToken().url(ConfigConstants.HX_URL + "chatgroups/" + groupId + "/users")
                .post(RequestBody.create(JSON, JSONObject.toJSONString(map)))
                .build();
        OkHttpClient client = new OkHttpClient();
        Response response;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            logger.info("批量添加群成员，响应体解析异常", ConfigConstants.LOG_WARN);
            e.printStackTrace();
            return false;
        }
        if (response == null) {
            return false;
        }
        //请求是否成功
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            //响应体是否为空
            if (responseBody == null) {
                logger.info("批量添加群成员，响应体为空", ConfigConstants.LOG_WARN);
                return false;
            }
            try {
                JSONObject jsonObject = JSONObject.parseObject(responseBody.string());
                System.out.println(jsonObject);
                return true;
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            logger.info("批量添加群成员，环信token请求失败", ConfigConstants.LOG_WARN);
            return false;
        }
        logger.info("批量添加群成员，环信token未知错误", ConfigConstants.LOG_ERROR);
        return false;
    }

    /**
     * 批量删除群成员
     * 移除群成员，用户名之间用英文逗号分隔。如果所有被移除用户均不是群成员，将移除失败，并返回错误
     * groupId	群组id
     * memebers	环信用户id 用户名之间用英文逗号分隔
     *
     * @return 添加结果，true表示添加成功，false表示添加失败
     */
    public static boolean batchDeleteGroupMember(String groupId, String memebers) {
        Request request = getRequestBuilderHeadWithToken().url(ConfigConstants.HX_URL + "chatgroups/" + groupId + "/users/" + memebers)
                .delete()
                .build();
        OkHttpClient client = new OkHttpClient();
        Response response;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            logger.info("批量移除群成员，响应体解析异常", ConfigConstants.LOG_WARN);
            e.printStackTrace();
            return false;
        }
        if (response == null) {
            return false;
        }
        //请求是否成功
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            //响应体是否为空
            if (responseBody == null) {
                logger.info("批量移除群成员，响应体为空", ConfigConstants.LOG_WARN);
                return false;
            }
            try {
                JSONObject jsonObject = JSONObject.parseObject(responseBody.string());
                System.out.println(jsonObject);
                return true;
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            logger.info("批量移除群成员，环信token请求失败", ConfigConstants.LOG_WARN);
            return false;
        }
        logger.info("批量移除群成员，环信token未知错误", ConfigConstants.LOG_ERROR);
        return false;
    }


    /**
     * 添加群管理员
     * 为群组添加多个成员，一次最多可以添加60位成员。如果所有用户均已是群成员，将添加失败，并返回错误。
     * groupId	群组id
     * newadmin	添加的新管理员用户 ID
     *
     * @return 添加结果，true表示添加成功，false表示添加失败
     */
    public static String addGroupAdmin(String groupId, String newadmin) {
        String body = "{\"newadmin\":\"" + newadmin + "\"}";
        Request request = getRequestBuilderHeadWithToken().url(ConfigConstants.HX_URL + "chatgroups/" + groupId + "/admin")
                .post(RequestBody.create(JSON, JSONObject.toJSONString(body)))
                .build();
        OkHttpClient client = new OkHttpClient();
        Response response;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            logger.info("添加群管理，响应体解析异常", ConfigConstants.LOG_WARN);
            e.printStackTrace();
            return "";
        }
        if (response == null) {
            return "";
        }
        //请求是否成功
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            //响应体是否为空
            if (responseBody == null) {
                logger.info("添加群管理，响应体为空", ConfigConstants.LOG_WARN);
                return "";
            }
            try {
                JSONObject jsonObject = JSONObject.parseObject(responseBody.string());
                System.out.println(jsonObject);
                return JSONObject.parseObject(jsonObject.get("data").toString()).toJSONString();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            logger.info("添加群管理，环信token请求失败", ConfigConstants.LOG_WARN);
            return "";
        }
        logger.info("添加群管理，环信token未知错误", ConfigConstants.LOG_ERROR);
        return "";
    }

    /**
     * 批量删除群成员
     * 移除群成员，用户名之间用英文逗号分隔。如果所有被移除用户均不是群成员，将移除失败，并返回错误
     * groupId	群组id
     * memebers	环信用户id
     *
     * @return 添加结果，true表示添加成功，false表示添加失败
     */
    public static String deleteGroupAdmin(String groupId, String oldadmin) {
        Request request = getRequestBuilderHeadWithToken().url(ConfigConstants.HX_URL + "chatgroups/" + groupId + "/admin/" + oldadmin)
                .delete()
                .build();
        OkHttpClient client = new OkHttpClient();
        Response response;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            logger.info("移除群管理，响应体解析异常", ConfigConstants.LOG_WARN);
            e.printStackTrace();
            return "";
        }
        if (response == null) {
            return "";
        }
        //请求是否成功
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            //响应体是否为空
            if (responseBody == null) {
                logger.info("移除群管理，响应体为空", ConfigConstants.LOG_WARN);
                return "";
            }
            try {
                JSONObject jsonObject = JSONObject.parseObject(responseBody.string());
                System.out.println(jsonObject);
                return JSONObject.parseObject(jsonObject.get("data").toString()).toJSONString();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            logger.info("移除群管理，环信token请求失败", ConfigConstants.LOG_WARN);
            return "";
        }
        logger.info("移除群管理，环信token未知错误", ConfigConstants.LOG_ERROR);
        return "";
    }


    /**
     * 转让群
     *
     * groupId	群组id
     * newowner	环信用户id
     */
    public static String transferGroup(String groupId, String newowner) {
        String body = "{\"newowner\":\"" + newowner + "\"}";
        Request request = getRequestBuilderHeadWithToken().url(ConfigConstants.HX_URL + "chatgroups/" + groupId)
                .put(RequestBody.create(JSON, body))
                .build();
        OkHttpClient client = new OkHttpClient();
        Response response;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            logger.info("转让群，响应体解析异常", ConfigConstants.LOG_WARN);
            e.printStackTrace();
            return "";
        }
        if (response == null) {
            return "";
        }
        //请求是否成功
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            //响应体是否为空
            if (responseBody == null) {
                logger.info("转让群，响应体为空", ConfigConstants.LOG_WARN);
                return "";
            }
            try {
                JSONObject jsonObject = JSONObject.parseObject(responseBody.string());
                System.out.println(jsonObject);
                return JSONObject.parseObject(jsonObject.get("data").toString()).toJSONString();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            logger.info("转让群，环信token请求失败", ConfigConstants.LOG_WARN);
            return "";
        }
        logger.info("转让群，环信token未知错误", ConfigConstants.LOG_ERROR);
        return "";
    }

    public static void main(String[] args) {
//        syncIMGroup();
    }

    /**
     * 同步环信群组至本地
     * @return
     */
    public static void syncIMGroup() {
        Request request = getRequestBuilderHeadWithToken()
                .url(ConfigConstants.HX_URL + "chatgroups")
                .build();
        OkHttpClient client = new OkHttpClient();
        Response response = null;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            logger.info("查看群组详细信息，响应体解析异常", ConfigConstants.LOG_WARN);
            e.printStackTrace();
        }
        //请求是否成功
        if (response.isSuccessful()) {
            ResponseBody responseBody = response.body();
            //响应体是否为空
            if (responseBody == null) {
                logger.info("查看群组详细信息，响应体为空", ConfigConstants.LOG_WARN);
            }
            try {
                JSONObject jsonObject = JSONObject.parseObject(responseBody.string());
                JSONArray data = jsonObject.getJSONArray("data");
                for (int i=0; i<data.size(); i++){
                    JSONObject group = (JSONObject) data.get(i);
                    String owner = group.get("owner").toString();
                    String userId = owner.substring(owner.indexOf("_")+1);
//                        System.out.println(group.get("groupid").toString()+"\n");

                    Map<String, Object> groupInfo = getGroupInfo(group.get("groupid").toString()).get(0);
                    List<Map<String, String>> affiliations = (List<Map<String, String>>) groupInfo.get("affiliations");
                    for (Map<String, String> affiliation : affiliations){
                        affiliation.get("member");
                        if (affiliation.get("member") != null){
                            System.out.println("insert into tb_entity_group_member(user_id, group_id, group_user_name, level, create_time, type) VALUES ("+affiliation.get("member")+",'" +
                                    group.get("groupid").toString() + "','备注'," +0+",now(),"+0+");");
                        }
                        if (affiliation.get("owner") != null) {
                            System.out.println("insert into tb_entity_group_member(user_id, group_id, group_user_name, level, create_time, type) VALUES ("+affiliation.get("owner")+",'" +
                                    group.get("groupid").toString() + "','备注'," +0+",now(),"+2+");");
                        }
                    }

                }
                System.out.println(jsonObject);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            logger.info("查看群组详细信息，环信token请求失败", ConfigConstants.LOG_WARN);
        }
        logger.info("查看群组详细信息，环信token未知错误", ConfigConstants.LOG_ERROR);
        return ;
    }
}
